package com.langChain4j.conversation.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.base.frame.common.service.BaseServiceImpl;
import com.base.frame.exception.BusinessException;
import com.langChain4j.api.enums.CommonErrorEnum;
import com.langChain4j.api.enums.SessionEnum;
import com.langChain4j.api.vo.AgentChatVo;
import com.langChain4j.api.entity.AgentDialogSession;
import com.langChain4j.conversation.controller.vo.ConversationSessionVo;
import com.langChain4j.conversation.vo.MessageRequest;
import com.langChain4j.conversation.vo.SessionRequest;
import com.langChain4j.conversation.repository.AgentDialogSessionRepository;
import com.langChain4j.conversation.service.AgentConversationService;
import com.langChain4j.model.factory.AgentLoaderHandler;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ChatMessageDeserializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 智能体对话交互服务实现类
 *
 * @author linjun
 */
@Slf4j
@Service
public class AgentConversationServiceImpl extends BaseServiceImpl<AgentDialogSession, AgentDialogSessionRepository> implements AgentConversationService {

    @Override
    public AgentDialogSession queryBySessionId(String sessionId) {
        AgentDialogSession session = baseMapper.selectById(sessionId);
        if (ObjectUtil.isNull(session)) {
            throw new BusinessException(CommonErrorEnum.SESSION_NOT_EXISTS);
        }
        return session;
    }

    @Override
    public AgentDialogSession queryActiveBySessionId(String sessionId) {
        QueryWrapper<AgentDialogSession> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("session_id", sessionId)
                .eq("status", SessionEnum.SESSION_STATUS_ACTIVE.getCode());
        AgentDialogSession session = baseMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNull(session)) {
            throw new BusinessException(CommonErrorEnum.SESSION_NOT_EXISTS);
        }
        return session;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ConversationSessionVo startConversation(SessionRequest sessionRequest) {
        // 检查是否存在有效的会话记录
        QueryWrapper<AgentDialogSession> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("session_id", sessionRequest.getSessionId())
                   .eq("status", SessionEnum.SESSION_STATUS_ACTIVE.getCode());
        AgentDialogSession existingSession = baseMapper.selectOne(queryWrapper);

        if (ObjectUtil.isNotNull(existingSession)) {
            return ConversationSessionVo.builder()
                    .sessionId(existingSession.getSessionId())
                    .userId(existingSession.getUserId())
                    .agentId(existingSession.getAgentId())
                    .startTime(existingSession.getStartTime())
                    .build();
        }

        // 初始化新的会话并保存到数据库
        AgentDialogSession session = new AgentDialogSession();
        session.setSessionId(sessionRequest.getSessionId());
        session.setUserId(sessionRequest.getUserId());
        session.setAgentId(sessionRequest.getAgentId());
        session.setStatus(SessionEnum.SESSION_STATUS_ACTIVE.getCode());
        session.setStartTime(LocalDateTime.now());

        try {
            // 创建会话处理，此处只做简单处理
            baseMapper.insert(session);
            return ConversationSessionVo.builder()
                    .sessionId(session.getSessionId())
                    .userId(session.getUserId())
                    .agentId(session.getAgentId())
                    .startTime(session.getStartTime())
                    .build();
        } catch (Exception e) {
            log.error("创建会话失败：{}", e.getMessage(), e);
            throw new BusinessException(CommonErrorEnum.SESSION_CREATE_ERROR);
        }
    }

    @Override
    public Flux<String> sendMessage(MessageRequest messageRequest) {
        AgentDialogSession session = this.queryActiveBySessionId(messageRequest.getSessionId());
        List<ChatMessage> historyMessage = new ArrayList<>();
        if (StringUtils.isNotBlank(session.getContextMemory())) {
            List<ChatMessage> messages = ChatMessageDeserializer.messagesFromJson(session.getContextMemory());
            historyMessage.addAll(messages);
        }
        AgentChatVo chatVo = AgentChatVo.builder()
                .sessionId(messageRequest.getSessionId())
                .message(messageRequest.getMessageContent())
                .modelName(messageRequest.getModuleCode())
                .historyMessage(historyMessage)
                .build();

        // 使用工厂模式获取加载器
        AgentLoaderHandler handler = new AgentLoaderHandler(messageRequest.getModuleCode());
//            String responseText = handler.getAgentLoader().chat(chatVo);
        return handler.getAgentLoader().streamChat(chatVo);
    }

    @Override
    public ConversationSessionVo endConversation(SessionRequest sessionRequest) {
        AgentDialogSession session = this.queryActiveBySessionId(sessionRequest.getSessionId());
        // 设置会话结束时间并标记为完成状态
        session.setEndTime(LocalDateTime.now());
        session.setStatus(SessionEnum.SESSION_STATUS_END.getCode());
        session.setUpdateTime(LocalDateTime.now());

        try {
            // 增加会话结束处理
            baseMapper.updateById(session);
            return ConversationSessionVo.builder()
                    .sessionId(session.getSessionId())
                    .endTime(session.getEndTime())
                    .status(session.getStatus())
                    .build();
        } catch (Exception e) {
            log.error("结束会话失败：{}", e.getMessage(), e);
            throw new BusinessException(CommonErrorEnum.SESSION_END_ERROR);
        }
    }

    @Override
    public ConversationSessionVo getConversationHistory(SessionRequest sessionRequest) {
        // 查询指定会话的所有交互记录
        AgentDialogSession session = this.queryBySessionId(sessionRequest.getSessionId());
        if (ObjectUtil.isNull(session)) {
            throw new BusinessException(CommonErrorEnum.SESSION_NOT_EXISTS);
        }
        return ConversationSessionVo.builder()
                .sessionId(session.getSessionId())
                .userId(session.getUserId())
                .agentId(session.getAgentId())
                .contextMemory(session.getContextMemory())
                .startTime(session.getStartTime())
                .endTime(session.getEndTime())
                .status(session.getStatus())
                .build();
    }
}